package com.shark.mq;

import com.rabbitmq.client.Channel;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;

/**
 * @auther shark
 * @create 2024-08-12 21:16
 *
 * 故障3解决：消费端消息确认Case演示
 *  4 = For
 */
//@Component
@Slf4j
public class MyMessageListener4ACK
{
    public static final String EXCHANGE_DIRECT = "exchange.direct.order";
    public static final String QUEUE_NAME  = "queue.order";
    public static final String ROUTING_KEY = "orderack";

    // 修饰监听方法
    @RabbitListener(
            // 设置绑定关系
            bindings = @QueueBinding(
                    // 配置交换机信息：durable 设置为 true 表示队列持久化；autoDelete 设置为 false 表示关闭自动删除
                    exchange = @Exchange(value = EXCHANGE_DIRECT, durable = "true", autoDelete = "false"),

                    // 配置队列信息：durable 设置为 true 表示队列持久化；autoDelete 设置为 false 表示关闭自动删除
                    value = @Queue(value = QUEUE_NAME, durable = "true", autoDelete = "false"),

                    // 配置路由键信息
                    key = {ROUTING_KEY}
            ))
    public void processMessage(String dataString, Message message, Channel channel) throws IOException
    {

        // 1、获取当前消息的 deliveryTag 值备用
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        System.out.println("---deliveryTag: "+deliveryTag);

        try
        {
            // 2、正常业务操作
            log.info("消费端接收到消息内容：" + dataString);

            int age = 10/0;

            // 3、给 RabbitMQ 服务器返回 ACK 确认信息 业务处理成功：手动返回ACK信息，表示消息成功消费
            channel.basicAck(deliveryTag, false); //取值为false：仅为指定的deliveryTag返回ACK信息
        } catch (Exception e) {
            // 4、获取信息，看当前消息是否曾经被投递过
            Boolean redelivered = message.getMessageProperties().getRedelivered();
            System.out.println("---redelivered: "+redelivered);

            if (!redelivered) {
                // 5、如果没有被投递过，那就重新放回队列，重新投递，再试一次 boolean requeue(重回队列)
                channel.basicNack(deliveryTag, false, true);
                System.out.println("-----basicNack");
            } else {
                // 6、如果已经被投递过，且这一次仍然进入了 catch 块，那么返回拒绝且不再放回队列,那么这条消息的处理就到此为止
                channel.basicReject(deliveryTag, false);
                System.out.println("-----basicReject");
            }

        }
    }
}

